#include "extensionwindow.h"
#include "extension.h"
#include "extensionview.h"
#include <QCloseEvent>
#include <QVBoxLayout>

namespace yc {

ExtensionWindow::ExtensionWindow(QWidget* parent, Qt::WindowFlags f)
    : QWidget(parent, Qt::Window | f), force_stop_requested_(false)
{
    setupUi();
}

ExtensionWindow::ExtensionWindow(Extension* extension, QWidget* parent, Qt::WindowFlags f)
    : QWidget(parent, Qt::Window | f), extension_(extension), force_stop_requested_(false)
{
    setupUi();
}

ExtensionWindow::~ExtensionWindow()
{
    stopExtension();
}

Extension* ExtensionWindow::extension() const
{
    return extension_;
}

void ExtensionWindow::setExtension(Extension* extension)
{
    if (extension_ != extension) {
        if (extension_) {
            extension_->deleteLater();
        }
        extension_ = extension;
        if (extension_ && extension_->view()) {
            qobject_cast<QVBoxLayout*>(layout())->addWidget(extension_->view(), 1);
        }
    }
}

void ExtensionWindow::stopExtension(ResolveCallback resolve)
{
    if (extension_) {
        ResolveCallback stop_resolve = [=, this] {
            stopExtension();
            if (resolve) {
                resolve();
            }
        };
        requestStopExtension(stop_resolve, RejectCallback());
    } else {
        if (resolve) {
            resolve();
        }
    }
    return;
}

void ExtensionWindow::requestStop()
{
    if (!stopping_) {
        stopping_ = true;
        close();
    }
}

void ExtensionWindow::stop()
{
    if (!stopping_) {
        force_stop_requested_ = true;
        stopping_ = true;
        stopExtension();
        close();
    }
}

void ExtensionWindow::changeEvent(QEvent* e)
{
    QWidget::changeEvent(e);
    if (extension_ && QEvent::WindowStateChange == e->type()) {
        if (ExtensionView* p = extension_->view()) {
            QWindowStateChangeEvent* sce = static_cast<QWindowStateChangeEvent*>(e);
            p->onWindowStateChanged(windowState(), sce->oldState());
        }
    }
}

void ExtensionWindow::closeEvent(QCloseEvent* e)
{
    if (!force_stop_requested_ && extension_) {
        ResolveCallback resolve = [this] {
            force_stop_requested_ = true;
            close();
        };
        RejectCallback reject = [this] {
            stopping_ = false;
            Q_EMIT stopIgnored();
        };
        requestStopExtension(resolve, reject);
        // 检查是否是已经停止了
        if (!force_stop_requested_) {
            e->ignore();
            return;
        }
    }

    // 关闭
    QWidget::closeEvent(e);
    // 通知停止
    stopping_ = false;
    Q_EMIT stopped();
}

void ExtensionWindow::requestStopExtension(ResolveCallback resolve, RejectCallback reject)
{
    Q_ASSERT(extension_);
    if (resolve) {
        connect(extension_, &Extension::stopped, this, [this, resolve] {
            disconnect(extension_, &Extension::stopped, this, nullptr);
            disconnect(extension_, &Extension::stopIgnored, this, nullptr);
            resolve();
        });
    }
    connect(extension_, &Extension::stopIgnored, this, [this, reject] {
        disconnect(extension_, &Extension::stopped, this, nullptr);
        disconnect(extension_, &Extension::stopIgnored, this, nullptr);
        if (reject) {
            reject();
        }
    });
    extension_->requestStop();
}

void ExtensionWindow::stopExtension()
{
    if (extension_) {
        extension_->stop();
        extension_->deleteLater();
        extension_ = nullptr;
    }
}

void ExtensionWindow::setupUi()
{
    QVBoxLayout* vl = new QVBoxLayout(this);
    vl->setContentsMargins(0, 0, 0, 0);
    if (extension_ && extension_->view()) {
        vl->addWidget(extension_->view(), 1);
    }
}
} // namespace yc
